Skip to content

Support the authentication proofs of Symfony 8.2 - #322

Open
nicolas-grekas wants to merge 2 commits into
scheb:sf-8.2from
nicolas-grekas:authentication-proofs
Open

nicolas-grekas wants to merge 2 commits into
scheb:sf-8.2from
nicolas-grekas:authentication-proofs

Conversation

@nicolas-grekas

@nicolas-grekas nicolas-grekas commented Sep 15, 2026 •

Copy link
Copy Markdown
Contributor

Symfony 8.2 adds a "recent authentication" system to the Security component, and three of its pieces touch what this bundle decorates or replaces. This PR adapts the bundle to them while keeping it working unchanged on Symfony 7.4, 8.0 and 8.1.

What Symfony 8.2 adds (symfony/symfony#66064 has the whole design):

Why it matters for this bundle

  1. Scheb\TwoFactorBundle\Security\Authentication\AuthenticationTrustResolver decorates security.authentication.trust_resolver and implements the three interface methods only. On 8.2 the voter therefore finds no isAuthenticatedRecently() on it, logs the deprecation and denies IS_AUTHENTICATED_RECENTLY for every application using the bundle. The two methods are added, delegating to the decorated resolver when it has them, and answering false for a TwoFactorTokenInterface, like isFullFledged() does.
  2. TwoFactorToken implements TokenInterface directly with its own attribute bag, so it has no proofs. Since the bundle swaps the token on AuthenticationTokenCreatedEvent, the TwoFactorToken is what Symfony's listener sees when the first factor succeeds, and the password proof was lost. Both methods are added and delegate to the wrapped token, which is the one that ends up authenticated once 2fa completes.
  3. The listeners that check the code add an AuthenticationMethodBadge once it is valid: otp for a backup code, or the method the provider says it verifies. That is a new optional AuthenticationMethodProviderInterface with one method, getAuthenticationMethod(): string, implemented by the TOTP, Google Authenticator and email providers (all return otp). A provider that does not implement it keeps working, and its proof is recorded as unspecified by Symfony.

With the three, a Symfony 8.2 policy can require a second factor, e.g. isset($token->getAuthenticationProofs()['otp']), which is the level-of-assurance use case the RFC describes.

Backward compatibility

  • method_exists() / class_exists() guards everywhere the 8.2 API is used, so nothing changes on older Symfony versions; the added methods on the resolver and the token are plain additions.
  • TwoFactorProviderInterface is untouched; the new interface is opt-in.
  • The otp value for the email provider is a judgement call: RFC 8176 has no value for an emailed code, and otp ("one-time password") is the closest. mca (multiple-channel) would be the alternative if you prefer to distinguish it from an authenticator app.

The tests for the badge are skipped until AuthenticationMethodBadge exists in the installed Symfony version; everything else runs on 8.1. phpcs, psalm and php-cs-fixer are clean.

@scheb

scheb commented Sep 15, 2026

Copy link
Copy Markdown
Owner

Good stuff! Will have a closer look at it, once I find some time. Thanks for opening up the PR!

Is there any timeline on this?

@nicolas-grekas

Copy link
Copy Markdown
Contributor Author

This should ship in 8.2, end of November

@scheb

scheb commented Sep 15, 2026

Copy link
Copy Markdown
Owner

Should be doable :)

@nicolas-grekas

Copy link
Copy Markdown
Contributor Author

All merged in 8.2-dev now 馃殌

@scheb scheb left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Already looks very good!

I think the AuthenticationMethodBadge should be added in a different place. Except, it is necessary for the badge to be present right after the authenticate(Request $request): Passport method is called. Is it?

Comment thread src/bundle/Security/Http/Authenticator/TwoFactorAuthenticator.php Outdated
@scheb

scheb commented Oct 10, 2026

Copy link
Copy Markdown
Owner

@nicolas-grekas Would you please rebase and re-target the PR to the sf-8.2 branch, which has a build against Symfony 8.2 development versions configured. Thanks!

@nicolas-grekas
nicolas-grekas changed the base branch from 8.x to sf-8.2 October 10, 2026 16:17
@nicolas-grekas

Copy link
Copy Markdown
Contributor Author

Done!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants